[update] Amazon CloudFrontのorigin request policyでblock list形式(“all except”)をサポートしました!
はじめに
清水です。AWSのCDNサービスであるAmazon CloudFrontでorigin request policyに「指定した以外のものすべて」というようなblock list形式での指定ができるようになるアップデートがありました。アップデート情報は本日(2023/02/24 17:00)時点でAmazon CloudFront Developer GuideのDocument historyに記載されています。(2023/02/22付でのDocument更新でした。)
Document history - Amazon CloudFront
2020年7月にAmazon CloudFrontでサポートされたCache policyとOrigin request policy、これまでCache KeyのQuery stringsならびにCookiesでは「指定した以外のものすべて」という「All except」な指定が可能でした。Origin request policyでもこのような指定ができれば便利だし設定の手間も減るんだけど、という要望もあったかと思います。このたび、Origin request policyのHeaders、Query strings、Cookiesの3種の設定すべてで「All except」な設定ができるようになりました!
またあわせてmanaged origin request policyでこの「All except」な指定方法を使ったAllViewerExceptHostHeader
が選択できるようになっています。(上記、Document historyで本アップデートの下に記載されている項目がこのアップデートとなります。)こちらはそのpolicy名称の通り、Host
header以外のHeadersのすべて、そしてすべてのQuery Strings、すべてのCookiesをオリジンリクエスト時に使用するpolicyとなっています。Amazon CloudFront Developer Guideによるとこのpolicyは、Amazon API GatewayおよびAWS Lambda function URLオリジンで利用することを想定されているとのことです。
これまでのOrigin request policyの設定方法とアップデート内容の確認
まずはOrigin request policyでの「All except」なblock list形式での指定ができる前の設定方法と、今回のアップデート内容である「All except」な設定方法をそれぞれ確認してみましょう。
Cache policyとOrigin request policyがサポートされた2022年7月のAWS Blogを確認してみます。
- Amazon CloudFront Announces Cache and Origin Request Policies | Networking & Content Delivery
- 日本語翻訳版
Origin request policyのHeadersの指定ではNone
、Whitelist
、All Viewer headers and whitelisted CloudFront-* Headers
、そしてAll viewer headers
のいずれかから選択する、というかたちでした。そしてQuery stringsとCookiesについては、All
、None
、Whitelist
のいずれかからの選択です。Whitelist形式でオリジンリクエスト時に含める内容を明示的に指定することはできていましたが、「指定したものを除いたすべて」というBlock list形式の指定はできなかったわけです。
Amazon CloudFront Announces Cache and Origin Request Policies | Networking & Content Delivery
なお、Origin request policyではなくCache policyのほうのCache keyについては、Query StringsとCookiesに対して、All-except
として「指定したものを除いたすべて」という指定がこのころから可能でした。
Amazon CloudFront Announces Cache and Origin Request Policies | Networking & Content Delivery
さて、今回のアップデートではOrigin request policyでAll-except
な指定ができるようになったわけです。さっそくCloudFrontのマネジメントコンソール、Create origin request policy画面を確認してみましょう。Headers、Query strings、CookiesのいずれでもAll except
な指定ができるようになっていますね!
Origin request policyでall exceptな指定をしてみる
マネジメントコンソールからOrigin request policyでAll except
な指定ができるようになっていることが確認できました。続いて、実際にこの設定を行ったCloudFront Distributionを作成し、動作を確認してみましょう。
オリジンサーバの準備
まずはオリジンサーバの準備です。EC2上でApache HTTP Server + PHPが稼働する環境を準備しました。このEC2のPublic IPv4 DNSをCloudFrontのOrigin domainとして指定します。
EC2上では以下2つのパスで下記のコードを準備しました。オリジン側で受け取ったHeaders(含むCookies)、Query Stringsをレスポンスとして返すという内容です。
/origin-request-policy-all-except/all-check.php
/origin-request-policy-all-except/all-except-check.php
<?php foreach (getallheaders() as $name => $value) { echo "$name: $value"."\n"; } echo "Query-Strings: ".$_SERVER['QUERY_STRING']."\n"; ?>
All exceptなorigin request policyの作成
続いて今回のアップデート内容All except
を使ったOrigin request policyを作成します。以下の内容のpolicyとしました。
- Headers
All viewer headers except
Host
- Query strings
All query strings except
ref
- Cookies
All cookies except
session_id
任意のNameとDescriptionを指定して、policyを作成します。
All except
を使ったOrigin request policyが作成できました!
Distributionとbehaviorの作成
All exceptを使ったOrigin request policyが作成できました。続いてこのpolicyを使用するCloudFront Distributionを作成します。以下、Distribution作成のポイントとなる点のみスクリーンショットを掲示します。
Originは先ほど準備したEC2を使用します。Origin domainの項目でC2のPublic IPv4 DNSを指定します。
Default cache behavior(Default (*)
では先ほど作成したAll exceptを使ったOrigin request policyは使わずmanaged policyのAllViewerAndCloudFrontHeaders-2022-06
を指定しています。Cache policyはCachingDisabled
としました。
Distributionが作成できたら、default以外のbehaviorを1つ作成します。対象となるPath patternは以下です、先ほどオリジンとなるEC2に準備したファイルの1つですね。
- Path pattern
/origin-request-policy-all-except/all-except-check.php
このPath patternに対し、先ほど作成したAll exceptを使ったOrigin request policyを設定します。 (ここでは名称がAllExceptTest
というpolicyとなります。)またCache policyはCachingDisabled
を選択しました。
Distributionならびに追加のbehaviorの設定ができました。
All exceptなorigin request policyの動作確認
それでは実際に、All exceptを指定したorigin request policyの動作を確認してみましょう。まずはこれを指定していないbehavior(Default cache behavior)となる以下のパスです。AllViewerAndCloudFrontHeaders-2022-06
のorigin request policyが適用されます。Query StringsとCookiesも以下のように指定しました。
- Path
/origin-request-policy-all-except/all-check.php
- Query Strings
ref=0123abc&split-pages=false
- Cookies
session_id=01234abcd
curlコマンドでCloudFrontにリクエストを行います。レスポンス内容でオリジン側が受けっとたリクエストの内容を確認しましょう。オリジン側ではQuery Strings、Cookiesのいずれも確認できていることがわかりますね。またHost headerはリクエストと同じcloudfront.net
ドメインとなっています、これもOrigin request policyでオリジンリクエストの際にそのまま使用するよう(オリジンに転送するよう)設定しているからですね。
% curl "https://d2vjxxxxxxxxxx.cloudfront.net/origin-request-policy-all-except/all-check.php?ref=0123abc&split-pages=false" --cookie "session_id=01234abcd" Host: d2vjxxxxxxxxxx.cloudfront.net User-Agent: curl/7.79.1 X-Amz-Cf-Id: EXmSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXJw== Connection: Keep-Alive Via: 2.0 b3f4xxxxxxxxxxxxxxxxxxxxxxxx8bd0.cloudfront.net (CloudFront) Cookie: session_id=01234abcd X-Forwarded-For: 2axx:xxxx:xxxx:xx::xx:x85 Accept: */* CloudFront-Is-Mobile-Viewer: false CloudFront-Is-Tablet-Viewer: false CloudFront-Is-SmartTV-Viewer: false CloudFront-Is-Desktop-Viewer: true CloudFront-Is-IOS-Viewer: false CloudFront-Is-Android-Viewer: false CloudFront-Viewer-HTTP-Version: 2.0 CloudFront-Viewer-Country: JP CloudFront-Viewer-Country-Name: Japan CloudFront-Viewer-Country-Region: 13 CloudFront-Viewer-Country-Region-Name: Tokyo CloudFront-Viewer-City: Tokyo CloudFront-Viewer-Postal-Code: 102-0082 CloudFront-Viewer-Time-Zone: Asia/Tokyo CloudFront-Viewer-Latitude: 35.68930 CloudFront-Viewer-Longitude: 139.68990 CloudFront-Forwarded-Proto: https CloudFront-Viewer-Address: 2axx:xxxx:xxxx:xx::xx:x85:28xx4 CloudFront-Viewer-TLS: TLSv1.3:TLS_AES_128_GCM_SHA256:fullHandshake Query-Strings: ref=0123abc&split-pages=false
続いて本題となる、All exceptなorigin request policyを指定したbehaviorにリクエストをして確認してみましょう。以下の内容でリクエストを行いました。(Pathからall exceptなorigin request policyを指定したbehaviorに振り分けられます。)
- Path
/origin-request-policy-all-except/all-except-check.php
- Query Strings
ref=0123abc&split-pages=false
- Cookies
session_id=01234abcd
オリジン側で受けっとたリクエスト、Host
headerについてはcloudfront.net
ドメインではなくOrigin domainで指定したEC2のPublic IPv4 DNSとなっていることがわかります。こちらはDeveloper Guideにも記載がありますが、Host
headerを除外するよう設定した場合、CloudFront側で新たなHost
headerとしてOrigin domainが使用されるという挙動となっています。またQuery Stringsについては指定したref
に該当するref=0123abc
が除外されています。Cookieについてもsession_id
に該当するsession_id=01234abcd
がまるっと除外されていることがわかりますね。
% curl "https://d2vjxxxxxxxxxx.cloudfront.net/origin-request-policy-all-except/all-except-check.php?ref=0123abc&split-pages=false" --cookie "session_id=01234abcd" Host: ec2-18-XXX-XXX-172.ap-northeast-1.compute.amazonaws.com User-Agent: curl/7.79.1 X-Amz-Cf-Id: S0JmXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXhA== Connection: Keep-Alive Via: 2.0 af58xxxxxxxxxxxxxxxxxxxxxxxx6a10.cloudfront.net (CloudFront) X-Forwarded-For: 2axx:xxxx:xxxx:xx::xx:x85 Accept: */* CloudFront-Is-Mobile-Viewer: false CloudFront-Is-Tablet-Viewer: false CloudFront-Is-SmartTV-Viewer: false CloudFront-Is-Desktop-Viewer: true CloudFront-Is-IOS-Viewer: false CloudFront-Is-Android-Viewer: false CloudFront-Viewer-HTTP-Version: 2.0 CloudFront-Viewer-Country: JP CloudFront-Viewer-Country-Name: Japan CloudFront-Viewer-Country-Region: 13 CloudFront-Viewer-Country-Region-Name: Tokyo CloudFront-Viewer-City: Tokyo CloudFront-Viewer-Postal-Code: 102-0082 CloudFront-Viewer-Time-Zone: Asia/Tokyo CloudFront-Viewer-Latitude: 35.68930 CloudFront-Viewer-Longitude: 139.68990 CloudFront-Forwarded-Proto: https CloudFront-Viewer-Address: 2axx:xxxx:xxxx:xx::xx:x85:21xx2 CloudFront-Viewer-TLS: TLSv1.3:TLS_AES_128_GCM_SHA256:fullHandshake Query-Strings: split-pages=false
さらに同じPath(All exceptなorigin request policyが適用されるPath)へのリクエストで、Query StringsとCookiesを追加してリクエストを行ってみます。
- Path
/origin-request-policy-all-except/all-except-check.php
- Query Strings
language=ja&ref=0123abc&split-pages=false
- Cookies
cookie1=value1; session_id=01234abcd; cookie2=value2
追加したQuery StringsとCookiesの内容については、origin request policyでexceptとして指定はしていないので、オリジン側で確認ができます。またexceptとしてしていしたものは引き続きオリジン側では確認できません。またQuery Strings、Cookiesともに追加の際に、CloudFront側で除外対象となるものを真ん中になるよう指定してみたのですが、きれいに該当部分だけが除外されていることが確認できます。
% curl "https://d2vjxxxxxxxxxx.cloudfront.net/origin-request-policy-all-except/all-except-check.php?language=ja&ref=0123abc&split-pages=false" --cookie "cookie1=value1; session_id=01234abcd; cookie2=value2" Host: ec2-18-XXX-XXX-172.ap-northeast-1.compute.amazonaws.com User-Agent: curl/7.79.1 X-Amz-Cf-Id: gwf6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2g== Connection: Keep-Alive Via: 2.0 9c65xxxxxxxxxxxxxxxxxxxxxxxxf86c.cloudfront.net (CloudFront) Cookie: cookie1=value1; cookie2=value2 X-Forwarded-For: 2axx:xxxx:xxxx:xx::xx:x85 Accept: */* CloudFront-Is-Mobile-Viewer: false CloudFront-Is-Tablet-Viewer: false CloudFront-Is-SmartTV-Viewer: false CloudFront-Is-Desktop-Viewer: true CloudFront-Is-IOS-Viewer: false CloudFront-Is-Android-Viewer: false CloudFront-Viewer-HTTP-Version: 2.0 CloudFront-Viewer-Country: JP CloudFront-Viewer-Country-Name: Japan CloudFront-Viewer-Country-Region: 13 CloudFront-Viewer-Country-Region-Name: Tokyo CloudFront-Viewer-City: Tokyo CloudFront-Viewer-Postal-Code: 102-0082 CloudFront-Viewer-Time-Zone: Asia/Tokyo CloudFront-Viewer-Latitude: 35.68930 CloudFront-Viewer-Longitude: 139.68990 CloudFront-Forwarded-Proto: https CloudFront-Viewer-Address: 2axx:xxxx:xxxx:xx::xx:x85:24xx0 CloudFront-Viewer-TLS: TLSv1.3:TLS_AES_128_GCM_SHA256:fullHandshake Query-Strings: language=ja&split-pages=false
新たに追加されたManaged policy「AllViewerExceptHostHeader」も確認してみる
今回のアップデート内容であるorigin request policyでのAll except
を使用したHeaders/Query Strings/Cookiesの指定について確認ができました。さてこのアップデートと同じタイミングで、Managedな Origin request policyにAllViewerExceptHostHeader
という名称のものが追加されていることを冒頭でもお伝えしました。このManaged policyについて、CloudFrontマネジメントコンソールから確認してみましょう。
「Policies > Origin request」を確認します。Managed policiesの一覧にAllViewerExceptHostHeader
が追加されていますね。
このManaged policy AllViewerExceptHostHeader
の詳細についても確認してみましょう。HeadersではAll viewer headers except
でhost
が指定されています。CookiesとQuery stringsはどちらもAll
の設定です。
まとめ
Amazon CloudFrontのorigin request policyで「指定した以外のものすべて」というAll except
なHeaders/Query Strings/Cookiesの指定ができるようになったアップデートについてお伝えしました。これまで事前に想定しうるパターンを列挙、それらをすべてWhitelistで指定すれば同様のことは実現できなくはなかったのかもしれませんが、block list形式で指定したいという場合のズバリ解決策になるアップデートかと思います。あわせてアップデートのあったManaged policy AllViewerExceptHostHeader
のDeveloper Guide内の説明でもありましたが、オリジン側の要件としてHost
headerにCloudFront domainではなくOrigin domainが必要、という要件に対しての解決策になる本アップデート、他のケースにも色々と活用できるのではないでしょうか。
おまけ: Twitterに投稿された本アップデートの情報
(2023/02/27追記)
今回のCloudFrontのアップデートについて、CloudFrontの製品開発者と思われる方からTwitterに投稿されたコメントを発見しました。
@matthieunapoli Thanks for your feedback and connecting with me afterwards. I want to share that we've added blocklist support so you can forward all headers to your origin except the Host header.
We also made some related changes to make the experience better for developers: https://t.co/b6pKFbe8d1
— Cristian Graziano (@cristiangraz) February 23, 2023
もともと本アップデートについてはTwitter上でのフィードバックが発端となっていたようです。改めてフィードバックの大切さを実感しますよね。
またこのアップデートにあわせてManaged policy AllViewerExceptHostHeader
ほか、CloudFrontマネジメントコンソール上でも細かなアップデートがあったようです。以下、Tweetの引用で紹介したいと思います。
オリジンにAPI Gatewayなどを選択した場合に、デフォルトとなるCache policy/Origin request policyがそのオリジンに適したものになりました。このAPI Gatewayの例ではデフォルトのCache policyがCaching Disabled
に、またOrigin request policyが今回のアップデートのあったAllViewerExceptHostHeader
となっていますね。
2/ Set policy defaults out of the box.
For origins like API Gateway, we now automatically set default policies that work out of the box so customers can get up and running faster. pic.twitter.com/C5aaC2jflU
— Cristian Graziano (@cristiangraz) February 23, 2023
さらに、オリジンに対して不適切となるpolicyについては選択不可となりましました。このAPI Gatewayの例では、Origin request policyについてAll Viewer
はCloudFrontアクセス時のHost headerをオリジンリクエストの際にも利用してしまうので不適切です。(API Gatewayが正しく動作しません。)あらかじめマネジメントコンソール上でも選択不可となることで、不用意に設定してしまうことを防ぐことができますね。
3/ Prevent policy misconfiguration.
If the policy you're using has headers that don't work with the origin type, we prevent you from selecting it.
This validation works for both managed and custom policies. pic.twitter.com/H062naRUGv
— Cristian Graziano (@cristiangraz) February 23, 2023